# -*- coding: utf-8 -*-
from allpairspy import AllPairs as AllPairsPy
from urllib.parse import quote
from django.http import HttpResponse
from openpyxl.utils import get_column_letter
from openpyxl.workbook import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from rest_framework.validators import UniqueTogetherValidator

from dvadmin.design.models import AllPairs, NodeTypes, NodesHierarchy
from dvadmin.design.views.hierarchy import NodesHierarchySerializer
from dvadmin.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet


class AllPairsSerializer(CustomModelSerializer):
    """
    正交试验-序列化器
    """

    class Meta:
        model = AllPairs
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllPairs.objects.all(),
                fields=['name', 'factor', 'level'],
                message="名字、因子、水平必须唯一"
            )
        ]


class AllPairsViewSet(CustomModelViewSet):
    """
    正交试验 接口
    list:查询
    save:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = AllPairs.objects.all()
    serializer_class = AllPairsSerializer

    def create(self, request, *args, **kwargs):
        """
        正交试验 新增 eg.
        --------------------
        {
            "name":"项目授信申请",
            "node_type":"allpairs",
            "data":[
                {
                    "factor":"业务类型",
                    "level":"50万直租标准产品"
                },
                {
                    "factor":"产品类型",
                    "level":"常规回租"
                }
            ]
        }

        """
        name = request.data.get('name')
        node_type = request.data.get('node_type')
        data = request.data.get('data')

        instance = NodeTypes.objects.filter(description='testmodel').first()
        if instance is None:
            return ErrorResponse(msg="查询出错")

        parent = NodesHierarchy.objects.filter(name=name, node_order=0, node_type=instance, parent=None).first()
        if parent is not None:
            return ErrorResponse(msg="名称已存在")

        # Hierarchy新增1条testmodel，作为根节点
        data_hier = {"name": name, "node_order": 0, "node_type": instance.id, "parent": None}
        serializer = NodesHierarchySerializer(data=data_hier, request=request)
        serializer.is_valid(raise_exception=True)
        parent = serializer.save()

        instance = NodeTypes.objects.filter(description=node_type).first()
        if instance is None:
            return ErrorResponse(msg="查询出错")

        for i, item in enumerate(data):
            # Hierarchy新增1条allpairs，作为叶节点
            data_hier = {"name": name, "node_order": i, "node_type": instance.id, "parent": parent.id}
            serializer = NodesHierarchySerializer(data=data_hier, request=request)
            serializer.is_valid(raise_exception=True)
            hierarchy = serializer.save()

            # AllPairs新增1条，作为详情
            data_pairs = {"name": name, "factor": item['factor'], "level": item['level'], "hierarchy": hierarchy.id}
            serializer = AllPairsSerializer(data=data_pairs, request=request)
            serializer.is_valid(raise_exception=True)
            serializer.save()

        return DetailResponse(msg="成功")

    def list(self, request, *args, **kwargs):
        """正交试验 获取所有测试模型 """

        is_superuser = request.user.is_superuser
        if is_superuser:
            queryset = AllPairs.objects.all().values_list("hierarchy")
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            queryset = AllPairs.objects.filter(dept_belong_id__in=dept_list).values_list("hierarchy")      # allpairs id

        queryset = NodesHierarchy.objects.filter(id__in=queryset).values_list("parent")  # hier_id
        queryset = NodesHierarchy.objects.filter(id__in=queryset)  # testmodel
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = NodesHierarchySerializer(page, many=True, request=request)
            return self.get_paginated_response(serializer.data)
        serializer = NodesHierarchySerializer(queryset, many=True, request=request)
        return SuccessResponse(data=serializer.data, msg="获取成功")

    def retrieve(self, request, *args, **kwargs):
        """正交试验 生成测试模型 """

        pid = kwargs.get('pk')
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        results = AllPairs.objects.filter(hierarchy__in=hierarchy)
        factors = []
        for result in results:
            factors.append(result.factor)
        factors = list(set(factors))

        parameters = {}
        for factor in factors:
            row = []
            parirs = results.filter(factor=factor)
            for pair in parirs:
                row.append(pair.level)
            parameters[factor] = row
        data = {"id": instance.id, "name": instance.name, "params": parameters}
        return DetailResponse(data=data, msg="成功")

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def gen(self, request, *args, **kwargs):
        """正交试验 根据测试模型生成测试场景  """

        pid = request.query_params.get('id', None)
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept',flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        results = AllPairs.objects.filter(hierarchy__in=hierarchy)
        factors = []
        for result in results:
            factors.append(result.factor)
        factors = list(set(factors))

        parameters = []
        for factor in factors:
            row = []
            parirs = results.filter(factor=factor)
            for pair in parirs:
                row.append(pair.level)
            parameters.append(row)
        res = list(AllPairsPy(parameters))
        data = {"id": instance.id, "name": instance.name, "title": factors}
        page = self.paginate_queryset(res)
        if page is not None:
            data["body"] = page
            return self.get_paginated_response(data)
        data = {"id": instance.id, "name": instance.name, "title": factors, "body": res}
        return DetailResponse(data=data, msg="成功")

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def export(self, request, *args, **kwargs):
        """正交试验 导出模型和场景 """

        pid = request.query_params.get('id', None)
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        results = AllPairs.objects.filter(hierarchy__in=hierarchy)
        factors = []
        for result in results:
            factors.append(result.factor)
        factors = list(set(factors))

        parameters = []
        for factor in factors:
            row = []
            parirs = results.filter(factor=factor)
            for pair in parirs:
                row.append(pair.level)
            parameters.append(row)
        export_field_label = factors
        data = list(AllPairsPy(parameters))

        # 导出excel 表
        response = HttpResponse(content_type="application/msexcel")
        response["Access-Control-Expose-Headers"] = f"Content-Disposition"
        response["content-disposition"] = f'attachment;filename={quote(str(f"导出{instance.name}.xlsx"))}'
        wb = Workbook()
        ws1 = wb.create_sheet(index=0, title='测试建模')
        ws2 = wb.create_sheet(index=1, title='测试场景')

        ws1.append(['序号', '因子', '水平'])
        count = 2   # 列数
        column = 1
        width = 30  # 默认列宽
        for index, results in enumerate(parameters):
            results_list = []
            for h_index, val in enumerate(results):
                if val is None or val == "":
                    results_list.append("")
                else:
                    results_list.append(val)
                count = max(count, 2+len(results_list))

            ws1.append([index+1, factors[index], *results_list])
            column += 1

        row = get_column_letter(count)
        for index in range(count + 1):
            ws1.column_dimensions[get_column_letter(index + 2)].width = width
            if index > 2:
                ws1.cell(row=1, column=index).value = f"水平{index-2}"
        tab1 = Table(displayName="Table1", ref=f"A1:{row}{column}")

        export_field_label.insert(0, "序号")
        export_field_label.insert(1, "测试目的")
        header_data = export_field_label
        row = get_column_letter(len(export_field_label))
        column = 1
        ws2.append(header_data)
        for index, results in enumerate(data):
            results_list = []
            for h_index, val in enumerate(results):
                if val is None or val=="":
                    results_list.append("")
                else:
                    results_list.append(val)
            ws2.append([index + 1, instance.name, *results_list])
            column += 1
        # 　更新列宽
        for index in range(len(export_field_label)):
            ws2.column_dimensions[get_column_letter(index + 2)].width = width
        tab2 = Table(displayName="Table2", ref=f"A1:{row}{column}")  # 名称管理器
        style = TableStyleInfo(
            name="TableStyleLight11",
            showFirstColumn=True,
            showLastColumn=False,
            showRowStripes=True,
            showColumnStripes=True,
        )
        tab1.tableStyleInfo = style
        tab2.tableStyleInfo = style
        ws1.add_table(tab1)
        ws2.add_table(tab2)
        wb.save(response)
        return response
